﻿#region NeoPatterns
// 
// NeoPatterns framework is released under LGPLv3 license.
// See http://www.opensource.org/licenses/lgpl-3.0.html for more details.
// 
// Please visit http://neopatterns.wikidot.com for more information about NeoPatterns
// 
// Copyright (c) Pascal Craponne 2008
// 
#endregion

using System;
using System.Collections.Generic;
using NeoPatterns.Patterns.UniformAccessor;

namespace NeoPatterns.Patterns.UniformMutator
{
    public interface IUniformMutator : IUniformAccessor
    {
        /// <summary>
        /// Mutates the object (or creates a clone) with new specified values
        /// </summary>
        /// <typeparam name="TObject"></typeparam>
        /// <param name="holder"></param>
        /// <param name="memberValues"></param>
        /// <returns></returns>
        TObject Mutate<TObject>(TObject holder, IDictionary<MemberRef, object> memberValues);

        /// <summary>
        /// Registers a mutator, with explicit class type declaration
        /// </summary>
        /// <param name="classType"></param>
        /// <param name="handledMembers"></param>
        /// <param name="mutateFunc"></param>
        void RegisterMutator(Type classType, IList<string> handledMembers,
                             Func<object, IDictionary<MemberRef, object>, object> mutateFunc);

        /// <summary>
        /// Registers a mutator, with generic type declaration
        /// </summary>
        /// <typeparam name="TObject"></typeparam>
        /// <param name="handledMembers"></param>
        /// <param name="mutateFunc"></param>
        void RegisterMutator<TObject>(IList<string> handledMembers,
                                      Func<TObject, IDictionary<MemberRef, object>, TObject> mutateFunc);

        /// <summary>
        /// Registers a "clone as mutable"
        /// </summary>
        /// <param name="mutableType"></param>
        /// <param name="cloneAsMutable"></param>
        /// <param name="immutableType"></param>
        void RegisterCloneAsMutable(Type immutableType, Type mutableType, Func<object, object> cloneAsMutable);

        /// <summary>
        /// Registers a cloneAsMutable, generic version
        /// </summary>
        /// <typeparam name="TImmutable"></typeparam>
        /// <typeparam name="TMutable"></typeparam>
        /// <param name="cloneAsMutable"></param>
        void RegisterCloneAsMutable<TImmutable, TMutable>(Func<TImmutable, TMutable> cloneAsMutable);
    }
}
